/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_and_model.cpp                                                      *
 ****************************************************************************/

#include "elisa_and_model.h"

USING_ELISA

//--------------------------------------------------------------------------
// class CompoundModel
//--------------------------------------------------------------------------

CompoundModelRep::CompoundModelRep()
{
}

CompoundModelRep::CompoundModelRep(const CompoundModelRep & right) : ModelRep(right)
{
}

CompoundModelRep::~CompoundModelRep()
{
	SetModelRep::iterator it;
	for (it = _models.begin(); it != _models.end(); it++) {
		(*it)->delRef();
	}
}

//CompoundModelRep & CompoundModelRep::operator=(const CompoundModelRep & right) {}

int
CompoundModelRep::operator==(const CompoundModelRep & right) const
{
	// ishii
	return 0;
}

int
CompoundModelRep::operator!=(const CompoundModelRep & right) const
{
	// ishii
	return 0;
}

//## Other Operations (implementation)
void CompoundModelRep::addChild(ModelRep *m)
{
	_models.insert(m);
}

SetModelRep::iterator CompoundModelRep::beginModel()
{
	return _models.begin();
}

SetModelRep::const_iterator CompoundModelRep::const_beginModel() const
{
	return _models.begin();
}


SetModelRep::iterator CompoundModelRep::endModel()
{
	return _models.end();
}

SetModelRep::const_iterator CompoundModelRep::const_endModel() const
{
	return _models.end();
}

void CompoundModelRep::post(ModelRep & c)
{
	c.addRef();
	_models.insert(&c);
}

void CompoundModelRep::post(ModelRep *c)
{
	this->post(*c);
}

void CompoundModelRep::post(const SetModelRep & s)
{
	SetModelRep::const_iterator it;
	for (it = s.begin(); it != s.end(); ++it) {
		this->post(**it);
	}
}


//--------------------------------------------------------------------------
// class AndModel
//--------------------------------------------------------------------------

AndModel::AndModel()
	: CompoundModelRep()
{
}

AndModel::AndModel(const AndModel & right)
	: CompoundModelRep(right)
{
	_models = right._models;
}

AndModel::~AndModel()
{
}

//AndModel &
//AndModel::operator=(const AndModel & right) {}

int AndModel::operator==(const AndModel & right) const
{
	return(_models == right._models);
}

int AndModel::operator!=(const AndModel & right) const
{
	return(_models != right._models);
}

bool AndModel::serialize(std::ostream & os)
{
	return false;
}

bool AndModel::deserialize(std::istream & i)
{
	return false;
}


elisa::Model operator&&(const elisa::Model & m1, const elisa::Model & m2)
{
	elisa::AndModel *csp1 = dynamic_cast<elisa::AndModel *>(m1.model());
	elisa::AndModel *csp2 = dynamic_cast<elisa::AndModel *>(m2.model());

	elisa::SetModelRep::iterator it;
	if ((csp1 != 0) && (csp2 != 0)) {
		elisa::AndModel *result = new elisa::AndModel();
		for (it = csp1->beginModel(); it != csp1->endModel(); it++) {
			result->post(**it);
		}
		for (it = csp2->beginModel(); it != csp2->endModel(); it++) {
			result->post(**it);
		}
		return Model(result);
	} else if ((csp1 != 0) && (csp2 == 0)) {
		elisa::AndModel *result = new elisa::AndModel();
		for (it = csp1->beginModel(); it != csp1->endModel(); it++) {
			result->post(**it);
		}
		result->post(m2.model());
		return Model(result);
	} else if ((csp1 == 0) && (csp2 != 0)) {
		elisa::AndModel *result = new elisa::AndModel();
		for (it = csp2->beginModel(); it != csp2->endModel(); it++) {
			result->post(**it);
		}
		result->post(m1.model());
		return Model(result);
	} else {
		elisa::AndModel *result = new elisa::AndModel();
		if (m1.model() != 0) {
			result->post(m1.model());
		}
		if (m2.model() != 0) {
			result->post(m2.model());
		}
		return Model(result);
	}
}


elisa::Model& operator&=(elisa::Model & m1, const elisa::Model & m2)
{
	m1 = (m1 && m2);
	return m1;
}
